/*
 * Copyright (c) 2005, 2022, Oracle and/or its affiliates. All rights reserved.
 * ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 *
 */

package com.jse.server;
import java.lang.System.Logger;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.CopyOnWriteArrayList;


/**
 * {@code HttpContext} represents a mapping between the root {@link java.net.URI}
 * path of an application to a {@link HttpHandler} which is invoked to handle
 * requests destined for that path on the associated {@link HttpServer} or
 * {@link HttpsServer}.
 *
 * <p> {@code HttpContext} instances are created by the create methods in
 * {@code HttpServer} and {@code HttpsServer}.
 *
 * <p> A chain of {@link Filter} objects can be added to a {@code HttpContext}.
 * All exchanges processed by the context can be pre- and post-processed by each
 * {@code Filter} in the chain.
 *
 * @since 1.6
 */
public class HttpContext {

    private final String path;
    private final String protocol;
    private final HttpServer server;
    private final Map<String, Object> attributes = new ConcurrentHashMap<>();
    private final List<Filter> sfilters = new CopyOnWriteArrayList<>();
    /* user filters, set by applications */
    private final List<Filter> ufilters = new CopyOnWriteArrayList<>();
    private HttpHandler handler;

    /**
     * constructor is package private.
     */
    protected HttpContext(String protocol, String path, HttpHandler cb, HttpServer server) {
        if (path == null || protocol == null || path.length() < 1 || path.charAt(0) != '/') {
            throw new IllegalArgumentException("Illegal value for path or protocol");
        }
        this.protocol = protocol.toLowerCase(Locale.ROOT);
        this.path = path;
        if (!this.protocol.equals("http") && !this.protocol.equals("https")) {
            throw new IllegalArgumentException("Illegal value for protocol");
        }
        this.handler = cb;
        this.server = server;
    }

    /**
     * returns the handler for this context
     * 
     * @return the HttpHandler for this context
     */
    public HttpHandler getHandler() {
        return handler;
    }

    public void setHandler(HttpHandler h) {
        if (h == null) {
            throw new NullPointerException("Null handler parameter");
        }
        if (handler != null) {
            throw new IllegalArgumentException("handler already set");
        }
        handler = h;
    }

    /**
     * returns the path this context was created with
     * 
     * @return this context's path
     */
    public String getPath() {
        return path;
    }

    /**
     * returns the server this context was created with
     * 
     * @return this context's server
     */
    public HttpServer getServer() {
        return server;
    }

    /**
     * returns the protocol this context was created with
     * 
     * @return this context's path
     */
    public String getProtocol() {
        return protocol;
    }

    /**
     * returns a mutable Map, which can be used to pass
     * configuration and other data to Filter modules
     * and to the context's exchange handler.
     * <p>
     * Every attribute stored in this Map will be visible to
     * every HttpExchange processed by this context
     */
    public Map<String, Object> getAttributes() {
        return attributes;
    }

    Logger getLogger() {
        return server.getLogger();
    }
    
    public List<Filter> getFilters () {
        return ufilters;
    }

    List<Filter> getSystemFilters () {
        return sfilters;
    }
}
